//
//  MPCActionSheet.m
//  MPCActionSheet
//
//  Created by macRong on 08/28/2017.
//  Copyright (c) 2017 jxzjxz. All rights reserved.
//

#import "MPCActionSheet.h"
#import "MPCActionSheetViewController.h"
#import "MPCActionSheetC1Cell.h"
#import "MPCActionSheetC2Cell.h"
#import "MPCActionSheetDefines.h"

typedef NS_ENUM(NSInteger, MPCActionSheetType)
{
    MPCActionSheetC1Type = 0, // default
    MPCActionSheetC2Type,     // 左图 右文
    MPCActionSheetC3Type     // 上面自定义view， 下面文字
};


/**
 Handle click button.
 */
typedef void(^MPCActionSheetClickedHandler)(MPCActionSheet *actionSheet, NSInteger buttonIndex);

/**
 Handle action sheet will present.
 */
typedef void(^MPCActionSheetWillPresentHandler)(MPCActionSheet *actionSheet);
/**
 Handle action sheet did present.
 */
typedef void(^MPCActionSheetDidPresentHandler)(MPCActionSheet *actionSheet);

/**
 Handle action sheet will dismiss.
 */
typedef void(^MPCActionSheetWillDismissHandler)(MPCActionSheet *actionSheet, NSInteger buttonIndex);
/**
 Handle action sheet did dismiss.
 */
typedef void(^MPCActionSheetDidDismissHandler)(MPCActionSheet *actionSheet, NSInteger buttonIndex);


@interface MPCActionSheet ()
<
UITableViewDataSource,
UITableViewDelegate,
UIScrollViewDelegate
>

/**
 ActionSheetType.
 */
@property (nonatomic, assign) MPCActionSheetType sheetType;

/**
 Title.
 */
@property (nullable, nonatomic, copy) NSString *title;

/**
 Cancel button's title.
 */
@property (nullable, nonatomic, copy) NSString *cancelButtonTitle;

/**
 Cancel button's index.
 */
@property (nonatomic, assign, readonly) NSInteger cancelButtonIndex;

/**
 MPCActionSheet's delegate.
 */
@property (nullable, nonatomic, weak) id<MPCActionSheetDelegate> delegate;

/**
 All destructive buttons' set. You should give it the `NSNumber` type items.
 */
@property (nullable, nonatomic, strong) NSIndexSet *destructiveButtonIndexSet;

/**
 Destructive button's color. Default is RGB(254, 67, 37).
 */
@property (nonatomic, strong) UIColor *destructiveButtonColor;

/**
 Title's color. Default is `MPConfig.color.c10`.
 */
@property (nonatomic, strong) UIColor *titleColor;
/**
 Buttons' color, without destructive buttons. Default is `MPConfig.color.c12`.
 */
@property (nonatomic, strong) UIColor *buttonColor;
/**
 Cancel'Buttons' color, without destructive buttons. Default is `MPConfig.color.c10`.
 */
@property (nonatomic, strong) UIColor *cancelButtonColor;
/**
 Title's font. Default is `[UIFont YXFontOfSize:14.0f]`.
 */
@property (nonatomic, strong) UIFont *titleFont;
/**
 All buttons' font. Default is `[UIFont YXFontOfSize:18.0f]`.
 */
@property (nonatomic, strong) UIFont *buttonFont;
/**
 All buttons' height. Default is 49.0f;
 */
@property (nonatomic, assign) CGFloat buttonHeight;

/**
 If buttons' bottom view can scrolling. Default is NO.
 */
@property (nonatomic, assign, getter=canScrolling) BOOL scrolling;

/**
 Visible buttons' count. You have to set `scrolling = YES` if you want to set it.
 */
@property (nonatomic, assign) CGFloat visibleButtonCount;

/**
 Animation duration. Default is 0.3 seconds.
 */
@property (nonatomic, assign) CGFloat animationDuration;

/**
 Opacity of dark background. Default is 0.3f.
 */
@property (nonatomic, assign) CGFloat darkOpacity;

/**
 If you can tap darkView to dismiss. Defalut is NO, you can tap dardView to dismiss.
 */
@property (nonatomic, assign) BOOL darkViewNoTaped;

/**
 Clear blur effect. Default is NO, don't clear blur effect.
 */
@property (nonatomic, assign) BOOL unBlur;

/**
 Style of blur effect. Default is `UIBlurEffectStyleExtraLight`. iOS 8.0 +
 */
@property (nonatomic, assign) UIBlurEffectStyle blurEffectStyle;

/**
 Title's edge insets. Default is `UIEdgeInsetsMake(15.0f, 15.0f, 15.0f, 15.0f)`.
 */
@property (nonatomic, assign) UIEdgeInsets titleEdgeInsets;

/**
 Cell's separator color.
 */
@property (nonatomic, strong) UIColor *separatorColor;

/**
 Title can be limit in titleLinesNumber. Default is 0.
 */
@property (nonatomic, assign) NSInteger titleLinesNumber;

/**
 Auto hide when the device rotated. Default is NO, won't auto hide.
 */
@property (nonatomic, assign) BOOL autoHideWhenDeviceRotated;

// customView
@property (nonatomic, strong) UIView *customView;


/**
 MPCActionSheet clicked handler.
 */
@property (nullable, nonatomic, copy) MPCActionSheetClickedHandler     clickedHandler;
/**
 MPCActionSheet will present handler.
 */
@property (nullable, nonatomic, copy) MPCActionSheetWillPresentHandler willPresentHandler;
/**
 MPCActionSheet did present handler.
 */
@property (nullable, nonatomic, copy) MPCActionSheetDidPresentHandler  didPresentHandler;
/**
 MPCActionSheet will dismiss handler.
 */
@property (nullable, nonatomic, copy) MPCActionSheetWillDismissHandler willDismissHandler;
/**
 MPCActionSheet did dismiss handler.
 */
@property (nullable, nonatomic, copy) MPCActionSheetDidDismissHandler  didDismissHandler;



@end

@implementation MPCActionSheet

- (void)dealloc
{
    NSLog(@"%s ✅",__FUNCTION__);
    
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

+ (instancetype)sheetWithTitle:(NSString *)title
                      delegate:(id<MPCActionSheetDelegate>)delegate
             cancelButtonTitle:(NSString *)cancelButtonTitle
             otherButtonTitles:(NSString *)otherButtonTitles, ...
{
    id eachObject;
    va_list argumentList;
    NSMutableArray *tempOtherButtonTitles = nil;
    if (otherButtonTitles)
    {
        tempOtherButtonTitles = [[NSMutableArray alloc] initWithObjects:otherButtonTitles, nil];
        va_start(argumentList, otherButtonTitles);
        
        while ((eachObject = va_arg(argumentList, id)))
        {
            [tempOtherButtonTitles addObject:eachObject];
        }
        
        va_end(argumentList);
    }
    
    return [[self alloc] initWithTitle:title
                              delegate:delegate
                     cancelButtonTitle:cancelButtonTitle
                 otherButtonTitleArray:tempOtherButtonTitles];
}

+ (instancetype)sheetWithImages:(nullable NSArray <NSString *> *)images
              otherButtonTitles:(nullable NSArray <NSString *> *)otherButtonTitles
                       delegate:(nullable id<MPCActionSheetDelegate>)delegate
{
    return [[self alloc]initWithImages:images
                     otherButtonTitles:otherButtonTitles
                              delegate:delegate];
}

+ (instancetype)sheetWithTitle:(NSString *)title
             cancelButtonTitle:(NSString *)cancelButtonTitle
                       clicked:(MPCActionSheetClickedHandler)clickedHandler
             otherButtonTitles:(NSString *)otherButtonTitles, ...
{
    id eachObject;
    va_list argumentList;
    NSMutableArray *tempOtherButtonTitles = nil;
    
    if (otherButtonTitles)
    {
        tempOtherButtonTitles = [[NSMutableArray alloc] initWithObjects:otherButtonTitles, nil];
        va_start(argumentList, otherButtonTitles);
        
        while ((eachObject = va_arg(argumentList, id)))
        {
            [tempOtherButtonTitles addObject:eachObject];
        }
        
        va_end(argumentList);
    }
    
    return [[self alloc] initWithTitle:title
                     cancelButtonTitle:cancelButtonTitle
                               clicked:clickedHandler
                 otherButtonTitleArray:tempOtherButtonTitles];
}

+ (instancetype)sheetWithCustomView:(nullable UIView *)customView
                      customsConfig:(MPCActionSheetConfig *)config
                  cancelButtonTitle:(nullable NSString *)cancelButtonTitle
                           delegate:(nullable id<MPCActionSheetDelegate>)delegate
                  otherButtonTitles:(nullable NSString *)otherButtonTitles, ... NS_REQUIRES_NIL_TERMINATION
{
    id eachObject;
    va_list argumentList;
    NSMutableArray *tempOtherButtonTitles = nil;
    
    if (otherButtonTitles)
    {
        tempOtherButtonTitles = [[NSMutableArray alloc] initWithObjects:otherButtonTitles, nil];
        va_start(argumentList, otherButtonTitles);
        
        while ((eachObject = va_arg(argumentList, id)))
        {
            [tempOtherButtonTitles addObject:eachObject];
        }
        
        va_end(argumentList);
    }
    
    return [[self alloc] initWithCustomView:customView customsConfig:config cancelButtonTitle:cancelButtonTitle delegate:delegate otherButtonTitles:tempOtherButtonTitles];
}

+ (instancetype)sheetWithTitle:(NSString *)title
             cancelButtonTitle:(NSString *)cancelButtonTitle
                    didDismiss:(MPCActionSheetDidDismissHandler)didDismissHandler
             otherButtonTitles:(NSString *)otherButtonTitles, ...
{
    id eachObject;
    va_list argumentList;
    NSMutableArray *tempOtherButtonTitles = nil;
    
    if (otherButtonTitles)
    {
        tempOtherButtonTitles = [[NSMutableArray alloc] initWithObjects:otherButtonTitles, nil];
        va_start(argumentList, otherButtonTitles);
        
        while ((eachObject = va_arg(argumentList, id)))
        {
            [tempOtherButtonTitles addObject:eachObject];
        }
        
        va_end(argumentList);
    }
    
    return [[self alloc] initWithTitle:title
                     cancelButtonTitle:cancelButtonTitle
                            didDismiss:didDismissHandler
                 otherButtonTitleArray:tempOtherButtonTitles];
}

+ (instancetype)sheetWithTitle:(NSString *)title
                      delegate:(id<MPCActionSheetDelegate>)delegate
             cancelButtonTitle:(NSString *)cancelButtonTitle
         otherButtonTitleArray:(NSArray<NSString *> *)otherButtonTitleArray
{
    return [[self alloc] initWithTitle:title
                              delegate:delegate
                     cancelButtonTitle:cancelButtonTitle
                 otherButtonTitleArray:otherButtonTitleArray];
}

+ (instancetype)sheetWithTitle:(NSString *)title
             cancelButtonTitle:(NSString *)cancelButtonTitle
                       clicked:(MPCActionSheetClickedHandler)clickedHandler
         otherButtonTitleArray:(NSArray<NSString *> *)otherButtonTitleArray
{
    return [[self alloc] initWithTitle:title
                     cancelButtonTitle:cancelButtonTitle
                               clicked:clickedHandler
                 otherButtonTitleArray:otherButtonTitleArray];
}

+ (instancetype)sheetWithTitle:(NSString *)title
             cancelButtonTitle:(nullable NSString *)cancelButtonTitle
                    didDismiss:(nullable MPCActionSheetDidDismissHandler)didDismissHandler
         otherButtonTitleArray:(nullable NSArray<NSString *> *)otherButtonTitleArray
{
    return [[self alloc] initWithTitle:title
                     cancelButtonTitle:cancelButtonTitle
                            didDismiss:didDismissHandler
                 otherButtonTitleArray:otherButtonTitleArray];
}

- (instancetype)initWithTitle:(NSString *)title
                     delegate:(id<MPCActionSheetDelegate>)delegate
            cancelButtonTitle:(NSString *)cancelButtonTitle
            otherButtonTitles:(NSString *)otherButtonTitles, ...
{
    if (self = [super init])
    {
        if (self.customConfig)
        {
            [self config:self.customConfig];
        }
        else
        {
            [self config:MPCActionSheetConfig.config];
        }
        
        id eachObject;
        va_list argumentList;
        NSMutableArray *tempOtherButtonTitles = nil;
        
        if (otherButtonTitles)
        {
            tempOtherButtonTitles = [[NSMutableArray alloc] initWithObjects:otherButtonTitles, nil];
            va_start(argumentList, otherButtonTitles);
            
            while ((eachObject = va_arg(argumentList, id)))
            {
                [tempOtherButtonTitles addObject:eachObject];
            }
            
            va_end(argumentList);
        }
        
        self.title             = title;
        self.delegate          = delegate;
        self.cancelButtonTitle = cancelButtonTitle;
        self.otherButtonTitles = tempOtherButtonTitles;
        
        [self setupView];
    }
    
    return self;
}

- (instancetype)initWithTitle:(NSString *)title
            cancelButtonTitle:(NSString *)cancelButtonTitle
                      clicked:(MPCActionSheetClickedHandler)clickedHandler
            otherButtonTitles:(NSString *)otherButtonTitles, ...
{
    if (self = [super init])
    {
        if (self.customConfig)
        {
            [self config:self.customConfig];
        }
        else
        {
            [self config:MPCActionSheetConfig.config];
        }
        
        id eachObject;
        va_list argumentList;
        NSMutableArray *tempOtherButtonTitles = nil;
        
        if (otherButtonTitles)
        {
            tempOtherButtonTitles = [[NSMutableArray alloc] initWithObjects:otherButtonTitles, nil];
            va_start(argumentList, otherButtonTitles);
            
            while ((eachObject = va_arg(argumentList, id)))
            {
                [tempOtherButtonTitles addObject:eachObject];
            }
            
            va_end(argumentList);
        }
        
        self.title             = title;
        self.cancelButtonTitle = cancelButtonTitle;
        self.clickedHandler    = clickedHandler;
        self.otherButtonTitles = tempOtherButtonTitles;
        
        [self setupView];
    }
    
    return self;
}

- (instancetype)initWithTitle:(NSString *)title
            cancelButtonTitle:(NSString *)cancelButtonTitle
                   didDismiss:(MPCActionSheetDidDismissHandler)didDismissHandler
            otherButtonTitles:(NSString *)otherButtonTitles, ...
{
    if (self = [super init])
    {
        if (self.customConfig)
        {
            [self config:self.customConfig];
        }
        else
        {
            [self config:MPCActionSheetConfig.config];
        }
        
        id eachObject;
        va_list argumentList;
        NSMutableArray *tempOtherButtonTitles = nil;
    
        if (otherButtonTitles)
        {
            tempOtherButtonTitles = [[NSMutableArray alloc] initWithObjects:otherButtonTitles, nil];
            va_start(argumentList, otherButtonTitles);
            
            while ((eachObject = va_arg(argumentList, id)))
            {
                [tempOtherButtonTitles addObject:eachObject];
            }
            
            va_end(argumentList);
        }
        
        self.title             = title;
        self.cancelButtonTitle = cancelButtonTitle;
        self.didDismissHandler = didDismissHandler;
        self.otherButtonTitles = tempOtherButtonTitles;
        
        [self setupView];
    }
    
    return self;
}

- (instancetype)initWithTitle:(NSString *)title
                     delegate:(id<MPCActionSheetDelegate>)delegate
            cancelButtonTitle:(NSString *)cancelButtonTitle
        otherButtonTitleArray:(NSArray<NSString *> *)otherButtonTitleArray
{
    if (self = [super init])
    {
        if (self.customConfig)
        {
            [self config:self.customConfig];
        }
        else
        {
            [self config:MPCActionSheetConfig.config];
        }
        self.sheetType = MPCActionSheetC1Type;
        
        self.title             = title;
        self.delegate          = delegate;
        self.cancelButtonTitle = cancelButtonTitle;
        self.otherButtonTitles = otherButtonTitleArray;
        
        [self setupView];
    }
    
    return self;
}

- (instancetype)initWithImages:(nullable NSArray <NSString *> *)images
             otherButtonTitles:(nullable NSArray <NSString *> *)otherButtonTitles
                     delegate:(id<MPCActionSheetDelegate>)delegate
{
    if (self = [super init])
    {
        if (self.customConfig)
        {
            [self config:self.customConfig];
        }
        else
        {
            [self config:MPCActionSheetConfig.config];
        }
        
        self.sheetType = MPCActionSheetC2Type;
        
        self.delegate          = delegate;
        self.images            = images;
        self.otherButtonTitles = otherButtonTitles;
        
        [self setupView];
    }
    
    return self;
}

- (instancetype)initWithTitle:(NSString *)title
            cancelButtonTitle:(NSString *)cancelButtonTitle
                      clicked:(MPCActionSheetClickedHandler)clickedHandler
        otherButtonTitleArray:(NSArray<NSString *> *)otherButtonTitleArray
{
    if (self = [super init])
    {
        if (self.customConfig)
        {
            [self config:self.customConfig];
        }
        else
        {
            [self config:MPCActionSheetConfig.config];
        }
        
        self.title             = title;
        self.cancelButtonTitle = cancelButtonTitle;
        self.clickedHandler    = clickedHandler;
        self.otherButtonTitles = otherButtonTitleArray;
        
        [self setupView];
    }
    
    return self;
}

- (instancetype)initWithCustomView:(nullable UIView *)customView
                     customsConfig:(MPCActionSheetConfig *)config
                  cancelButtonTitle:(nullable NSString *)cancelButtonTitle
                           delegate:(nullable id<MPCActionSheetDelegate>)delegate
                 otherButtonTitles:(nullable NSArray <NSString *> *)otherButtonTitles
{
    if (self = [super init])
    {
        if (config)
        {
            [self config:config];
        }
        else
        {
            [self config:MPCActionSheetConfig.config];
        }
        
        
        self.sheetType = MPCActionSheetC3Type;
        
        self.delegate              = delegate;
        self.customView            = customView;
        self.otherButtonTitles = otherButtonTitles;
        self.cancelButtonTitle = cancelButtonTitle;

        [self setupView];
    }
    
    return self;
}

- (instancetype)initWithTitle:(NSString *)title
            cancelButtonTitle:(NSString *)cancelButtonTitle
                   didDismiss:(MPCActionSheetDidDismissHandler)didDismissHandler
        otherButtonTitleArray:(NSArray<NSString *> *)otherButtonTitleArray
{
    if (self = [super init])
    {
        if (self.customConfig)
        {
            [self config:self.customConfig];
        }
        else
        {
            [self config:MPCActionSheetConfig.config];
        }
        
        self.title             = title;
        self.cancelButtonTitle = cancelButtonTitle;
        self.didDismissHandler = didDismissHandler;
        self.otherButtonTitles = otherButtonTitleArray;
        
        [self setupView];
    }
    
    return self;
}

- (instancetype)config:(MPCActionSheetConfig *)config
{
    _title                     = config.title;
    _cancelButtonTitle         = config.cancelButtonTitle;
    _destructiveButtonIndexSet = config.destructiveButtonIndexSet;
    _destructiveButtonColor    = config.destructiveButtonColor;
    _titleColor                = config.titleColor;
    _buttonColor               = config.buttonColor;
    _titleFont                 = config.titleFont;
    _buttonFont                = config.buttonFont;
    _buttonHeight              = config.buttonHeight;
    _scrolling                 = config.canScrolling;
    _visibleButtonCount        = config.visibleButtonCount;
    _animationDuration         = config.animationDuration;
    _darkOpacity               = config.darkOpacity;
    _darkViewNoTaped           = config.darkViewNoTaped;
    _unBlur                    = config.unBlur;
    _blurEffectStyle           = config.blurEffectStyle;
    _titleEdgeInsets           = config.titleEdgeInsets;
    _separatorColor            = config.separatorColor;
    _autoHideWhenDeviceRotated = config.autoHideWhenDeviceRotated;
    _titleLinesNumber          = config.titleLinesNumber;
    _cancelButtonColor         = config.cancelButtonColor;
    
    return self;
}

- (void)setupView
{
    NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
    [notificationCenter addObserver:self
                           selector:@selector(handleDidChangeStatusBarOrientation)
                               name:UIApplicationDidChangeStatusBarOrientationNotification
                             object:nil];
    
    UIView *bottomView = [[UIView alloc] init];
    [self addSubview:bottomView];
    [bottomView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.left.right.equalTo(self);
        
        CGFloat height =
        (self.title.length > 0 ? self.titleTextSize.height + 2.0f + (self.titleEdgeInsets.top + self.titleEdgeInsets.bottom) : 0) +
        (self.otherButtonTitles.count > 0 ? (self.canScrolling ? MIN(self.visibleButtonCount, self.otherButtonTitles.count) : self.otherButtonTitles.count) * self.buttonHeight : 0) +
        (self.cancelButtonTitle.length > 0 ? 5.0f + self.buttonHeight : 0) ;
        
        if (self.sheetType == MPCActionSheetC3Type)
        {
            if (_customView)
            {
                height += CGRectGetHeight(self.customView.frame);
            }
        }
        
        CGFloat c2Height = self.sheetType == MPCActionSheetC2Type ? 20+20 :0;
        
        make.height.equalTo(@(height+c2Height));
        make.bottom.equalTo(self).offset(height);
    }];
    self.bottomView = bottomView;
    
    UIView *darkView                = [[UIView alloc] init];
    darkView.alpha                  = 0;
    darkView.userInteractionEnabled = NO;
    darkView.backgroundColor        =     MPBConfig.color.c12;
    [self addSubview:darkView];
    [darkView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.left.right.equalTo(self);
        make.top.equalTo(self).priorityLow();
        make.bottom.equalTo(bottomView.mas_top);
    }];
    self.darkView = darkView;
    
    UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self
                                                                          action:@selector(darkViewClicked)];
    [darkView addGestureRecognizer:tap];
    
    UIView *whiteBgView         = [[UIView alloc] init];
    whiteBgView.backgroundColor = [UIColor whiteColor];
    [bottomView addSubview:whiteBgView];
    [whiteBgView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.edges.equalTo(bottomView);
    }];
    self.whiteBgView = whiteBgView;
    
    
    // ?
    UIView *cView;
    if (self.sheetType == MPCActionSheetC3Type)
    {
        CGFloat heig = CGRectGetHeight(self.customView.frame);
        [bottomView addSubview:self.customView];
        [self.customView mas_makeConstraints:^(MASConstraintMaker *make) {
            make.top.equalTo(bottomView).offset(0);
            make.left.equalTo(bottomView);
            make.right.equalTo(bottomView);
            make.height.equalTo(@(heig));
        }];
        
        cView = self.customView;
    }
    else
    {
        UILabel *titleLabel      = [[UILabel alloc] init];
        titleLabel.text          = self.title;
        titleLabel.font          = self.titleFont;
        titleLabel.numberOfLines = 0;
        titleLabel.textColor     = self.titleColor;
        titleLabel.textAlignment = NSTextAlignmentCenter;
        [bottomView addSubview:titleLabel];
        [titleLabel mas_makeConstraints:^(MASConstraintMaker *make) {
            make.top.equalTo(bottomView).offset(self.title.length > 0 ? self.titleEdgeInsets.top : 0);
            make.left.equalTo(bottomView).offset(self.titleEdgeInsets.left);
            make.right.equalTo(bottomView).offset(-self.titleEdgeInsets.right);
            
            CGFloat height = self.title.length > 0 ? self.titleTextSize.height + 2.0f : 0;  // Prevent omit
            make.height.equalTo(@(height));
        }];
        self.titleLabel = titleLabel;
        cView = titleLabel;
    }

    
    UITableView *tableView    = [[UITableView alloc] init];
    tableView.backgroundColor = [UIColor whiteColor];
    tableView.dataSource      = self;
    tableView.delegate        = self;
    [bottomView addSubview:tableView];
    [tableView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.left.right.equalTo(bottomView);
        CGFloat topSep = self.title.length > 0 ? self.titleEdgeInsets.bottom : 0;
        if (self.sheetType == MPCActionSheetC2Type)
        {
            topSep = 20;
        }
        make.top.equalTo(cView.mas_bottom).offset(topSep);
        CGFloat height = self.otherButtonTitles.count * self.buttonHeight;
        make.height.equalTo(@(height));
    }];
    

    tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
    self.tableView = tableView;
    
    UIView *lineView  = [[UIView alloc] init];
    lineView.backgroundColor = self.separatorColor;
    lineView.contentMode   = UIViewContentModeBottom;
    lineView.clipsToBounds = YES;
    [bottomView addSubview:lineView];
    [lineView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.left.right.equalTo(bottomView);
        make.bottom.equalTo(tableView.mas_top);
        make.height.equalTo(@0.5f);
    }];
    self.lineView = lineView;
    self.lineView.hidden = !self.title || self.title.length == 0;
    
    UIView *divisionView         = [[UIView alloc] init];
    divisionView.alpha           = 0.4f;
    divisionView.backgroundColor = self.separatorColor;
    [bottomView addSubview:divisionView];
    [divisionView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.left.right.equalTo(bottomView);
        make.top.equalTo(tableView.mas_bottom);
        
        CGFloat height = self.cancelButtonTitle.length > 0 ? 5.0f : 0;
        make.height.equalTo(@(height));
    }];
    self.divisionView = divisionView;

    UIButton *cancelButton       = [UIButton buttonWithType:UIButtonTypeCustom];
    cancelButton.backgroundColor = [UIColor clearColor];
    cancelButton.titleLabel.font = self.buttonFont;
    [cancelButton setTitle:self.cancelButtonTitle forState:UIControlStateNormal];
    [cancelButton setTitleColor:self.cancelButtonColor forState:UIControlStateNormal];
    [cancelButton setBackgroundImage:[UIImage MPC_imageWithColor:self.separatorColor]
                            forState:UIControlStateHighlighted];
    [cancelButton addTarget:self
                     action:@selector(cancelButtonClicked)
           forControlEvents:UIControlEventTouchUpInside];
    [bottomView addSubview:cancelButton];
    [cancelButton mas_makeConstraints:^(MASConstraintMaker *make) {
        make.left.right.equalTo(bottomView);
        make.bottom.equalTo(bottomView);
        
        CGFloat height = self.cancelButtonTitle.length > 0 ? self.buttonHeight : 0;
        make.height.equalTo(@(height));
    }];
    
    if (!self.unBlur)
    {
        [self blurBottomBgView];
    }
    else
    {
        whiteBgView.hidden = NO;
    }
    
    self.cancelButton = cancelButton;
}

- (void)appendButtonsWithTitles:(NSString *)titles, ...
{
    id eachObject;
    va_list argumentList;
    NSMutableArray *tempButtonTitles = nil;
    
    if (titles)
    {
        tempButtonTitles = [[NSMutableArray alloc] initWithObjects:titles, nil];
        va_start(argumentList, titles);
    
        while ((eachObject = va_arg(argumentList, id)))
        {
            [tempButtonTitles addObject:eachObject];
        }
        
        va_end(argumentList);
    }
    
    self.otherButtonTitles = [self.otherButtonTitles arrayByAddingObjectsFromArray:tempButtonTitles];
    
    [self.tableView reloadData];
    [self updateBottomView];
    [self updateTableView];
}

- (void)appendButtonWithTitle:(NSString *)title atIndex:(NSInteger)index
{
#ifdef DEBUG
    NSAssert(index != 0, @"Index 0 is cancel button");
    NSAssert(index <= self.otherButtonTitles.count + 1, @"Index crossed");
#endif
    
    NSMutableArray<NSString *> *arrayM = [NSMutableArray arrayWithArray:self.otherButtonTitles];
    [arrayM insertObject:title atIndex:index - 1];
    self.otherButtonTitles = [NSArray arrayWithArray:arrayM];
    
    [self.tableView reloadData];
    [self updateBottomView];
    [self updateTableView];
}

- (void)appendButtonsWithTitles:(NSArray<NSString *> *)titles atIndexes:(NSIndexSet *)indexes
{
#ifdef DEBUG
    NSAssert(titles.count == indexes.count, @"Count of titles differs from count of indexs");
#endif
    
    NSMutableIndexSet *indexSetM = [[NSMutableIndexSet alloc] init];
    [indexes enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL * _Nonnull stop) {
#ifdef DEBUG
        NSAssert(idx != 0, @"Index 0 is cancel button");
        NSAssert(idx <= self.otherButtonTitles.count + indexes.count, @"Index crossed");
#endif
        
        [indexSetM addIndex:idx - 1];
    }];
    
    NSMutableArray<NSString *> *arrayM = [NSMutableArray arrayWithArray:self.otherButtonTitles];
    [arrayM insertObjects:titles atIndexes:indexSetM];
    self.otherButtonTitles = [NSArray arrayWithArray:arrayM];
    
    [self.tableView reloadData];
    [self updateBottomView];
    [self updateTableView];
}
    
- (void)handleDidChangeStatusBarOrientation
{
    if (self.autoHideWhenDeviceRotated)
    {
        [self hideWithButtonIndex:self.cancelButtonIndex];
    }
}

- (void)blurBottomBgView
{
//    self.whiteBgView.hidden = YES;
    
    if (!self.blurEffectView)
    {
        UIBlurEffect *blurEffect           = [UIBlurEffect effectWithStyle:self.blurEffectStyle];
        UIVisualEffectView *blurEffectView = [[UIVisualEffectView alloc] initWithEffect:blurEffect];
        [self.divisionView addSubview:blurEffectView];
        [blurEffectView mas_makeConstraints:^(MASConstraintMaker *make) {
            make.edges.equalTo(self.divisionView);
        }];
        self.blurEffectView = blurEffectView;
        [self.divisionView sendSubviewToBack:blurEffectView];
    }
}

- (void)unBlurBottomBgView
{
    self.whiteBgView.hidden = NO;
    
    if (self.blurEffectView)
    {
        [self.blurEffectView removeFromSuperview];
        self.blurEffectView = nil;
    }
}

#pragma mark - Setter & Getter

- (void)setTitle:(NSString *)title
{
    _title = [title copy];
    
    self.titleLabel.text = title;
    
    [self updateTitleLabel];
    
    [self.tableView mas_updateConstraints:^(MASConstraintMaker *make) {
        make.top.equalTo(self.titleLabel.mas_bottom).offset(self.title.length > 0 ? self.titleEdgeInsets.bottom : 0);
    }];
    
    self.lineView.hidden = !self.title || self.title.length == 0;
}

- (void)setCancelButtonTitle:(NSString *)cancelButtonTitle
{
    _cancelButtonTitle = [cancelButtonTitle copy];
    
    [self.cancelButton setTitle:cancelButtonTitle forState:UIControlStateNormal];
    [self updateCancelButton];
}

- (void)setDestructiveButtonIndexSet:(NSIndexSet *)destructiveButtonIndexSet
{
    _destructiveButtonIndexSet = destructiveButtonIndexSet;
    
    if ([destructiveButtonIndexSet containsIndex:0])
    {
        [self.cancelButton setTitleColor:self.destructiveButtonColor forState:UIControlStateNormal];
    }
    else
    {
        [self.cancelButton setTitleColor:self.buttonColor forState:UIControlStateNormal];
    }
    
    [self.tableView reloadData];
}

- (void)setUnBlur:(BOOL)unBlur
{
    _unBlur = unBlur;
    
    if (unBlur)
    {
        [self unBlurBottomBgView];
    }
    else
    {
        [self blurBottomBgView];
    }
}

- (void)setBlurEffectStyle:(UIBlurEffectStyle)blurEffectStyle
{
    _blurEffectStyle = blurEffectStyle;
    
    [self unBlurBottomBgView];
    [self blurBottomBgView];
}

- (void)setTitleFont:(UIFont *)aTitleFont
{
    _titleFont = aTitleFont;
    
    self.titleLabel.font = aTitleFont;
    [self updateBottomView];
    [self updateTitleLabel];
}

- (void)setButtonFont:(UIFont *)aButtonFont
{
    _buttonFont = aButtonFont;
    
    self.cancelButton.titleLabel.font = aButtonFont;
    [self.tableView reloadData];
}

- (void)setDestructiveButtonColor:(UIColor *)aDestructiveButtonColor
{
    _destructiveButtonColor = aDestructiveButtonColor;
    
    if ([self.destructiveButtonIndexSet containsIndex:0])
    {
        [self.cancelButton setTitleColor:self.destructiveButtonColor forState:UIControlStateNormal];
    }
    else
    {
        [self.cancelButton setTitleColor:self.buttonColor forState:UIControlStateNormal];
    }
    
    [self.tableView reloadData];
}

- (void)setTitleColor:(UIColor *)aTitleColor
{
    _titleColor = aTitleColor;
    self.titleLabel.textColor = aTitleColor;
}

- (void)setButtonColor:(UIColor *)aButtonColor
{
    _buttonColor = aButtonColor;
    
    [self.cancelButton setTitleColor:aButtonColor forState:UIControlStateNormal];
    [self.tableView reloadData];
}

- (void)setButtonHeight:(CGFloat)aButtonHeight
{
    _buttonHeight = aButtonHeight;
    
    [self.tableView reloadData];
    [self updateBottomView];
    [self updateTableView];
    [self updateCancelButton];
}

- (NSInteger)cancelButtonIndex
{
    return 0;
}

- (void)setScrolling:(BOOL)scrolling
{
    _scrolling = scrolling;
    
    [self updateBottomView];
    [self updateTableView];
}

- (void)setVisibleButtonCount:(CGFloat)visibleButtonCount
{
    _visibleButtonCount = visibleButtonCount;
    
    [self updateBottomView];
    [self updateTableView];
}

- (void)setTitleEdgeInsets:(UIEdgeInsets)titleEdgeInsets
{
    _titleEdgeInsets = titleEdgeInsets;
    
    [self updateBottomView];
    [self updateTitleLabel];
    [self updateTableView];
}

- (void)setSeparatorColor:(UIColor *)separatorColor
{
    _separatorColor = separatorColor;
    
    self.lineView.backgroundColor = separatorColor;
    self.divisionView.backgroundColor = separatorColor;
    [self.cancelButton setBackgroundImage:[UIImage MPC_imageWithColor:separatorColor]
                                 forState:UIControlStateHighlighted];
    [self.tableView reloadData];
}

- (void)setTitleLinesNumber:(NSInteger)titleLinesNumber
{
  _titleLinesNumber = titleLinesNumber;
  
  [self updateBottomView];
  [self updateTitleLabel];
  [self updateTableView];
}

- (CGSize)titleTextSize
{
    CGSize size = CGSizeMake([UIScreen mainScreen].bounds.size.width -
                             (self.titleEdgeInsets.left + self.titleEdgeInsets.right),
                             MAXFLOAT);
    
    NSStringDrawingOptions opts = NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading;
    NSDictionary *attrs = @{NSFontAttributeName : self.titleFont};
    
    _titleTextSize = [self.title boundingRectWithSize:size
                                              options:opts
                                           attributes:attrs
                                              context:nil].size;
    
    if (self.titleLinesNumber != 0)
    {
      _titleTextSize.height = MIN(_titleTextSize.height, self.titleFont.lineHeight * self.titleLinesNumber);
    }
    
    return _titleTextSize;
}

- (NSString *)buttonTitleAtIndex:(NSInteger)index
{
    NSString *buttonTitle = nil;
    
    if (index == 0)
    {
        buttonTitle = self.cancelButtonTitle;
    }
    else
    {
        buttonTitle = self.otherButtonTitles[index - 1];
    }
    
    return buttonTitle;
}

#pragma mark - Update Views

- (void)updateBottomView
{
    [self.bottomView mas_updateConstraints:^(MASConstraintMaker *make) {
        
        CGFloat height = (self.title.length > 0 ?
                          self.titleTextSize.height + 2.0f + (self.titleEdgeInsets.top + self.titleEdgeInsets.bottom) :
                          0) + (self.otherButtonTitles.count > 0 ? (self.canScrolling ? MIN(self.visibleButtonCount, self.otherButtonTitles.count) : self.otherButtonTitles.count) * self.buttonHeight : 0) + (self.cancelButtonTitle.length > 0 ? 5.0f + self.buttonHeight : 0);
        make.height.equalTo(@(height));
    }];
}

- (void)updateTitleLabel
{
    [self.titleLabel mas_updateConstraints:^(MASConstraintMaker *make) {
        make.top.equalTo(self.bottomView).offset(self.title.length > 0 ? self.titleEdgeInsets.top : 0);
        make.left.equalTo(self.bottomView).offset(self.titleEdgeInsets.left);
        make.right.equalTo(self.bottomView).offset(-self.titleEdgeInsets.right);
        
        CGFloat height = self.title.length > 0 ? self.titleTextSize.height + 2.0f : 0;  // Prevent omit
        make.height.equalTo(@(height));
    }];
}

- (void)updateTableView
{
    if (!self.canScrolling)
    {
        [self.tableView mas_updateConstraints:^(MASConstraintMaker *make) {
            make.height.equalTo(@(self.otherButtonTitles.count * self.buttonHeight));
            make.top.equalTo(self.titleLabel.mas_bottom).offset(self.title.length > 0 ? self.titleEdgeInsets.bottom : 0);
        }];
    }
    else
    {
        [self.tableView mas_updateConstraints:^(MASConstraintMaker *make) {
            make.height.equalTo(@(MIN(self.visibleButtonCount, self.otherButtonTitles.count) * self.buttonHeight));
            make.top.equalTo(self.titleLabel.mas_bottom).offset(self.title.length > 0 ? self.titleEdgeInsets.bottom : 0);
        }];
    }
}

- (void)updateCancelButton
{
    [self.divisionView mas_updateConstraints:^(MASConstraintMaker *make) {
        CGFloat height = self.cancelButtonTitle.length > 0 ? 5.0f : 0;
        make.height.equalTo(@(height));
    }];
    
    [self.cancelButton mas_updateConstraints:^(MASConstraintMaker *make) {
        CGFloat height = self.cancelButtonTitle.length > 0 ? self.buttonHeight : 0;
        make.height.equalTo(@(height));
    }];
}


#pragma mark - Show & Hide

- (void)show
{
    if ([self.delegate respondsToSelector:@selector(willPresentActionSheet:)])
    {
        [self.delegate willPresentActionSheet:self];
    }
    
    if (self.willPresentHandler)
    {
        self.willPresentHandler(self);
    }
    
    MPCActionSheetViewController *viewController = [[MPCActionSheetViewController alloc] init];
    viewController.statusBarHidden = [UIApplication sharedApplication].statusBarHidden;
    viewController.statusBarStyle = [UIApplication sharedApplication].statusBarStyle;
    
    UIWindow *window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
    window.windowLevel = UIWindowLevelStatusBar;
    window.rootViewController = viewController;
    [window makeKeyAndVisible];
    self.window = window;
    
    [viewController.view addSubview:self];
    [self mas_makeConstraints:^(MASConstraintMaker *make) {
        make.edges.equalTo(viewController.view);
    }];
    
    [self.window layoutIfNeeded];
    
    __weak typeof(self) weakSelf = self;
    [UIView animateWithDuration:self.animationDuration delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{
        __strong typeof(weakSelf) strongSelf = weakSelf;
        
        strongSelf.darkView.alpha = strongSelf.darkOpacity;
        strongSelf.darkView.userInteractionEnabled = !strongSelf.darkViewNoTaped;
        
        [strongSelf.bottomView mas_updateConstraints:^(MASConstraintMaker *make) {
            make.bottom.equalTo(strongSelf);
        }];
        
        [strongSelf layoutIfNeeded];
        
    } completion:^(BOOL finished) {
        __strong typeof(weakSelf) strongSelf = weakSelf;
        
        if ([strongSelf.delegate respondsToSelector:@selector(didPresentActionSheet:)])
        {
            [strongSelf.delegate didPresentActionSheet:strongSelf];
        }
        
        if (strongSelf.didPresentHandler)
        {
            strongSelf.didPresentHandler(strongSelf);
        }
    }];
}

- (void)hideWithButtonIndex:(NSInteger)buttonIndex
{
    if ([self.delegate respondsToSelector:@selector(actionSheet:willDismissWithButtonIndex:)])
    {
        [self.delegate actionSheet:self willDismissWithButtonIndex:buttonIndex];
    }
    
    if (self.willDismissHandler)
    {
        self.willDismissHandler(self, buttonIndex);
    }
    
    __weak typeof(self) weakSelf = self;
    [UIView animateWithDuration:self.animationDuration delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{
        __strong typeof(weakSelf) strongSelf = weakSelf;
        
        strongSelf.darkView.alpha = 0;
        strongSelf.darkView.userInteractionEnabled = NO;
        
        [strongSelf.bottomView mas_updateConstraints:^(MASConstraintMaker *make) {
            CGFloat height = (strongSelf.title.length > 0 ? strongSelf.titleTextSize.height + 2.0f + (strongSelf.titleEdgeInsets.top + strongSelf.titleEdgeInsets.bottom) : 0) + (strongSelf.otherButtonTitles.count > 0 ? (strongSelf.canScrolling ? MIN(strongSelf.visibleButtonCount, strongSelf.otherButtonTitles.count) : strongSelf.otherButtonTitles.count) * strongSelf.buttonHeight : 0) + (strongSelf.cancelButtonTitle.length > 0 ? 5.0f + strongSelf.buttonHeight : 0);
            height += self.sheetType == MPCActionSheetC2Type ? 20+20 : 0;
            if (_customView)
            {
                height +=  self.sheetType == MPCActionSheetC3Type ? CGRectGetHeight(self.customView.frame) : 0;
            }
            make.bottom.equalTo(strongSelf).offset(height);
        }];
        
        [strongSelf layoutIfNeeded];
        
    } completion:^(BOOL finished) {
        __strong typeof(weakSelf) strongSelf = weakSelf;
        
        [strongSelf removeFromSuperview];
        
        strongSelf.window.rootViewController = nil;
        strongSelf.window.hidden = YES;
        strongSelf.window = nil;
        
        if ([strongSelf.delegate respondsToSelector:@selector(actionSheet:didDismissWithButtonIndex:)])
        {
            [strongSelf.delegate actionSheet:strongSelf didDismissWithButtonIndex:buttonIndex];
        }
        
        if (strongSelf.didDismissHandler)
        {
            strongSelf.didDismissHandler(strongSelf, buttonIndex);
        }
    }];
}

- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
    if (!self.canScrolling)
    {
        scrollView.contentOffset = CGPointMake(0, 0);
    }
}

#pragma mark - MPCActionSheet & UITableView Delegate

- (void)darkViewClicked
{
    [self cancelButtonClicked];
}

- (void)cancelButtonClicked
{
    if ([self.delegate respondsToSelector:@selector(actionSheet:clickedButtonAtIndex:)])
    {
        [self.delegate actionSheet:self clickedButtonAtIndex:-1];
    }
    
    if (self.clickedHandler)
    {
        self.clickedHandler(self, 0);
    }
    
    [self hideWithButtonIndex:0];
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    [tableView deselectRowAtIndexPath:indexPath animated:YES];
    
    if ([self.delegate respondsToSelector:@selector(actionSheet:clickedButtonAtIndex:)])
    {
        [self.delegate actionSheet:self clickedButtonAtIndex:indexPath.row];
    }
    
    if (self.clickedHandler)
    {
        self.clickedHandler(self, indexPath.row );
    }
    
    [self hideWithButtonIndex:indexPath.row ];
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return self.otherButtonTitles.count;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    if (self.sheetType == MPCActionSheetC1Type)
    {
        return [self tableView_C1:tableView cellForRowAtIndexPath:indexPath];
    }
    else if(self.sheetType == MPCActionSheetC2Type)
    {
        return [self tableView_C2:tableView cellForRowAtIndexPath:indexPath];
    }else if(self.sheetType == MPCActionSheetC3Type)
    {
        return [self tableView_C1:tableView cellForRowAtIndexPath:indexPath];
    }
    
    return [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil];
}

/** 样式一. 普通样式 C1 */
- (UITableViewCell *)tableView_C1:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *cellID = @"MPCActionSheetC1Cell_ID";
    MPCActionSheetC1Cell *cell = [tableView dequeueReusableCellWithIdentifier:cellID];
    
    if (!cell)
    {
        cell = [[MPCActionSheetC1Cell alloc] initWithStyle:UITableViewCellStyleDefault
                                         reuseIdentifier:cellID];
    }
    
    cell.titleLabel.font      = self.buttonFont;
    cell.titleLabel.textColor = self.buttonColor;
    cell.titleLabel.text = self.otherButtonTitles[indexPath.row];
    cell.cellSeparatorColor = self.separatorColor;
        
    if (indexPath.row == MAX(self.otherButtonTitles.count - 1, 0))
    {
        cell.tag = MPC_ACTION_SHEET_CELL_HIDDE_LINE_TAG;
    }
    else
    {
        cell.tag = MPC_ACTION_SHEET_CELL_NO_HIDDE_LINE_TAG;
    }
    
    if (self.destructiveButtonIndexSet)
    {
        if ([self.destructiveButtonIndexSet containsIndex:indexPath.row + 1])
        {
            cell.titleLabel.textColor = self.destructiveButtonColor;
        }
        else
        {
            cell.titleLabel.textColor = self.buttonColor;
        }
    }
    
    return cell;
}

/** 样式一. C2 */
- (UITableViewCell *)tableView_C2:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *cellID = @"MPCActionSheetC2Cell_ID";
    MPCActionSheetC2Cell *cell = [tableView dequeueReusableCellWithIdentifier:cellID];
    
    if (!cell)
    {
        cell = [[MPCActionSheetC2Cell alloc] initWithStyle:UITableViewCellStyleDefault
                                           reuseIdentifier:cellID];
    }
    
    cell.titleLabel.font      = [UIFont YXFontOfSize:16.0f];
    cell.titleLabel.textColor = self.buttonColor;
    cell.titleLabel.text      = self.otherButtonTitles[indexPath.row];
    cell.imageName            = self.images[indexPath.row];
    cell.cellSeparatorColor   = self.separatorColor;
    cell.lineView.hidden      = self.otherButtonTitles.count-1 == indexPath.row;
    
    return cell;
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    return self.buttonHeight;
}


@end
